<?php
namespace GMantuWeChat\Common;

/**
 * 微信公众平台接收处理中心，消息分发
 */
class Wechat{

    /**
     * 调试模式，将错误通过文本消息回复显示
     * @var boolean
     */
    private $debug;

    /**
     * 以数组的形式保存微信服务器每次发来的请求
     * @var array
     */
    private $request;
    
    private $db = null;

    /**
     * 初始化，判断此次请求是否为验证请求，并以数组形式保存
     * @param string $token 验证信息
     * @param boolean $debug 调试模式，默认为关闭
     */
    public function __construct($token, $db=null, $debug = FALSE) {
        //未通过消息真假性验证
       if ($this->isValid() && $this->validateSignature($token)) {
            return $_GET['echostr'];
        }
        //是否打印错误报告
        $this->debug = $debug;
        //接受并解析微信中心POST发送XML数据
        $xml = (array) simplexml_load_string($GLOBALS['HTTP_RAW_POST_DATA'], 'SimpleXMLElement', LIBXML_NOCDATA);

        //将数组键名转换为小写
        $this->request = array_change_key_case($xml, CASE_LOWER);
        
        if($db)
        {
            $this->db = $db;
        }
    }

    /**
     * 判断此次请求是否为验证请求
     * @return boolean
     */
    private function isValid() {
        return isset($_GET['echostr']);
    }

    /**
     * 判断验证请求的签名信息是否正确
     * @param  string $token 验证信息
     * @return boolean
     */
    private function validateSignature($token) {
        $signature = $_GET['signature'];
        $timestamp = $_GET['timestamp'];
        $nonce = $_GET['nonce'];
        $signatureArray = array($token, $timestamp, $nonce);
        sort($signatureArray, SORT_STRING);
        return sha1(implode($signatureArray)) == $signature;
    }

    /**
     * 获取本次请求中的参数，不区分大小
     * @param  string $param 参数名，默认为无参
     * @return mixed
     */
    protected function getRequest($param = FALSE) {
        if ($param === FALSE) {
            return $this->request;
        }
        $param = strtolower($param);
        if (isset($this->request[$param])) {
            return $this->request[$param];
        }
        return NULL;
    }
    
    /**
     * @desc    判断此用户是否已经存在数据库中了，如果没有，则新建
     * @note    会新建和更新2个数据库，user表格以及wechat表格
     * @note    支持oauth关注后的插入数据库
     */
    public function checkUser()
    {
        global $global_user;
        if($global_user != null)
            return;
        
        if(!isset($this->request['fromusername'])) {
            if (!isset($_GET['code'])) {
                $redirect_uri = urlencode("wechat_entry.php");
                $code = WeChatOAuth::getCode($redirect_uri, 1, "snsapi_userinfo");
            }
            else {
                $token = WeChatOAuth::getAccessTokenAndOpenId($_GET['code']);
                $user = WeChatOAuth::getUserInfo($token['access_token'], $token['openid']);
                //file_put_contents("log.txt", "****************" . serialize($user) . "****************", FILE_APPEND);
            }
        }
        else {
            // 接口调用频率500w，暂时达不到上限，暂不修改，每次都查询更新
            $user = UserManage::getUserInfo($this->request['fromusername']);
        }
        
        
        
        if($this->db && isset($user['openid'])) {
            $this->db->where("openid", $user['openid']);
            if(!empty($this->db->getOne(TABLE_CLD_USER_WECHAT))) {
                $this->db->update(TABLE_CLD_USER_WECHAT, $user);
            }
            else {
                /* 修改insert函数，支持数组插入了 in  2016-2-19 10:50
                foreach($user as $key => $value) {
                    if(is_array($value))
                        $user[$key] = json_encode($value);  // 插入数据库时不支持多维数组
                }
                */
                $this->db->insert(TABLE_CLD_USER_WECHAT, $user);
                
                // 更新userinfo表格，openid和account暂时设置成一致，不取unionid
                $userinfo = Array(
                    'account' => $user['openid'],
                    'wechat_id' => $user['openid']  // 不更新任何数据，备注等去wechat表格中去取值
                );
                $this->db->insert(TABLE_CLD_USER_INFO, $userinfo);
            }
            
            $global_user = $user;
        }
    }

    /**
     * 分析消息类型，并分发给对应的函数
     * @return void
     */
    public function run() {
        // checkuser主要是可以复用，后续获取用户的user信息就可以用此函数了
        $this->checkUser();
        
        $wh_req = new WechatRequest();
        return $wh_req->switchType($this->request, $this->db);
    }

    public function checkSignature()
    {
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];

        $token = WECHAT_TOKEN;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode( $tmpArr );
        $tmpStr = sha1( $tmpStr );

        if( $tmpStr == $signature ){
            echo $_GET['echostr'];
            return true;
        }else{
            return false;
        }
    }
}



